home *** CD-ROM | disk | FTP | other *** search
- /*
- Splitter: A Bars & Pipes Accessory for splitting a track into
- many tracks, according to a note map as used
- by the Pattern Tool for drum kits.
-
- Copyright (C) 1997 Richard Hagen
- This code is released into the Public Domain, and may be freely
- distributed in its original form.
-
- It is supplied ``as is'', and comes with no warranty.
- This program code was released because it might be useful as a
- starting point for other programmers. However, if any damage arises
- from its use, the original author will not be held liable.
-
- You are free to use and modify this code to your heart's content,
- provided you acknowledge me as the original author in any code
- that you might distribute which is based largely on this code.
-
- I acknowledge that the design of this accessory is influenced
- strongly by the example code supplied with the Rules for Tools
- package. However, I have made substantial contributions of my
- own.
-
- Richard Hagen
- richard@it.uq.edu.au
- August 1997
-
- History:
- Version 1.1: 19 August 1997
- Added ``Clear Note Map'' button.
- Tidied up some silly code.
- Version 1.0: 12 August 1997
- Initial Release.
- */
-
- #include <intuition/intuition.h>
- #include <libraries/dos.h>
- #include <libraries/gadtools.h>
- #include <exec/memory.h>
- #include <stdarg.h>
- #include <string.h>
- #include <stddef.h>
- #include <stdio.h>
-
- #include "bars.h"
-
- #include "myheader.h"
-
- /* -------------------------------------------------------------------- */
- /* ICON IMAGERY */
- /* -------------------------------------------------------------------- */
-
- /* I did these by hand to get the feel for what goes into a bitmap image.
- I really don't want to do it again! Can anyone point me at a good tool
- for doing the design for these sorts of things? */
-
- /* Normal icon. */
- static const __chip UWORD splitter_image_data[] = {
- /* Plane 0 */
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x7fff, 0xffff, 0xe000,
- 0x7fff, 0xffff, 0xe000,
- 0x38f0, 0x0c00, 0x0,
- 0x38f0, 0x0c00, 0x0,
- 0x0401, 0x8270, 0x0,
- 0x0401, 0x8270, 0x0,
- 0x0303, 0xc103, 0x0,
- 0x0303, 0xc103, 0x0,
- 0x7fff, 0xffff, 0xe000,
- 0x7fff, 0xffff, 0xe000,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
-
- /* Plane 1 */
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x7fff, 0xffff, 0xe000,
- 0x7fff, 0xffff, 0xe000,
- 0x2108, 0x4210, 0x8000,
- 0x2108, 0x4210, 0x8000,
- 0x2108, 0x4210, 0x8000,
- 0x2108, 0x4210, 0x8000,
- 0x2108, 0x4210, 0x8000,
- 0x2108, 0x4210, 0x8000,
- 0x7fff, 0xffff, 0xe000,
- 0x7fff, 0xffff, 0xe000,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
-
- /* Plane #2 */
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- };
-
- static const struct Image splitter_image = {
- 0, 0,
- 48, 34, 3,
- splitter_image_data,
- 0x1f, 0x00,
- NULL
- };
-
- /* Selected icon. */
- static const __chip UWORD splitter_onimage_data[] = {
- /* Plane 0 */
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x7fff, 0xffff, 0xe000,
- 0x7fff, 0xffff, 0xe000,
- 0x38f0, 0x0c00, 0x0,
- 0x38f0, 0x0c00, 0x0,
- 0x7fff, 0xffff, 0xe000,
- 0x7fff, 0xffff, 0xe000,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x7fff, 0xffff, 0xe000,
- 0x7fff, 0xffff, 0xe000,
- 0x0401, 0x8270, 0x0,
- 0x0401, 0x8270, 0x0,
- 0x7fff, 0xffff, 0xe000,
- 0x7fff, 0xffff, 0xe000,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x7fff, 0xffff, 0xe000,
- 0x7fff, 0xffff, 0xe000,
- 0x0303, 0xc103, 0x0,
- 0x0303, 0xc103, 0x0,
- 0x7fff, 0xffff, 0xe000,
- 0x7fff, 0xffff, 0xe000,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
-
- /* Plane 1 */
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
-
- /* Plane #2 */
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x7fff, 0xffff, 0xe000,
- 0x7fff, 0xffff, 0xe000,
- 0x2108, 0x4210, 0x8000,
- 0x2108, 0x4210, 0x8000,
- 0x7fff, 0xffff, 0xe000,
- 0x7fff, 0xffff, 0xe000,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x7fff, 0xffff, 0xe000,
- 0x7fff, 0xffff, 0xe000,
- 0x2108, 0x4210, 0x8000,
- 0x2108, 0x4210, 0x8000,
- 0x7fff, 0xffff, 0xe000,
- 0x7fff, 0xffff, 0xe000,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x7fff, 0xffff, 0xe000,
- 0x7fff, 0xffff, 0xe000,
- 0x2108, 0x4210, 0x8000,
- 0x2108, 0x4210, 0x8000,
- 0x7fff, 0xffff, 0xe000,
- 0x7fff, 0xffff, 0xe000,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0,
- };
-
- static const struct Image splitter_onimage = {
- 1, 0,
- 48, 34, 3,
- splitter_onimage_data,
- 0x1f, 0x00,
- NULL
- };
-
- /* Global Bars & Pipes functions pointer. */
- extern struct Functions *functions;
-
- /* Title for error requester. */
- static const char *error_title = "Splitter error";
-
- /* Puts up a simple requester for relaying error messages. */
- static void
- accessory_error(struct Window *window, /* Window to open requester in. */
- const char *s) /* String to put in the requester. */
- {
- const struct EasyStruct easy = {
- sizeof(struct EasyStruct),
- 0,
- error_title,
- s,
- "OK"
- };
-
- (void) EasyRequest(window, &easy, NULL);
- }
-
- /* -------------------------------------------------------------------- */
- /* Note Maps */
- /* -------------------------------------------------------------------- */
-
- /* Note maps are created by the Pattern tool when you edit a drum
- kit. Have a bit of a play with the drum map editing facility
- to get a feel for what data needs to be stored for a note map.
-
- The file containing the note map has the following format:
-
- Description Size Value Comment
-
- File ID 4 Bytes "NTMP"
- Length of File 4 Bytes File length - 8
- Offset to note data 4 Bytes
- Pointer to note data 4 Bytes Ignore this
- ?Spare byte? 1 Byte 0x00 ?
- MIDI Note to ID Map 128 Bytes
- ID to MIDI Note Map 128 Bytes
- ID to position Map 128 Bytes
- ?Spare Byte? 1 Byte 0x00 ?
- ?Map ID? 4 Bytes "DRUM" ?Different maps?
- Length of map 4 Bytes
- Length of map entry 4 Bytes 0x00000018
- Map entries -
- Pointer to next 4 Bytes 0 if last entry,
- otherwise, ignore
- Note name 15 Bytes 0 in last byte
- Note ID 1 Byte
- MIDI note 1 Byte
- Note position 1 Byte
- Flags 4 Bytes 0x00000001 == selected
- ?other flags?
-
- If anyone can help me out with the things marked ``?'', I'd really
- appreciate it! */
-
- /* Length of note name as stored in note map file. */
- #define NOTE_NAME_LEN 15
-
- /* Format of records stored in the note map file. */
- struct NotemapFileEntry {
- char name[NOTE_NAME_LEN];
- UBYTE id;
- UBYTE note;
- UBYTE pos;
- UWORD flags;
- };
-
- /* Strings for holding note names. */
- typedef char *Notemap[MIDI_NOTE_NUM]; /* Indexed by note number. */
-
- /* My accessory needs to remember a notemap, so I've bundled the two
- things together. */
- struct Splitter {
- struct Accessory accessory;
- Notemap *notemap;
- };
-
- /* My accessory. */
- struct Splitter splitter;
-
- /* Allocates, initialises and returns a new notemap.
- If something goes wrong, it returns NULL. */
- static Notemap *
- notemap_new(void)
- {
- register unsigned int i;
-
- /* Attempt the allocation and check for failure. */
- Notemap *notemap =
- (Notemap *)(*functions->myalloc)(sizeof(Notemap), MEMF_CLEAR);
- if (notemap == (Notemap *) NULL)
- {
- /* Allocation failed */
- return (Notemap *) NULL;
- }
-
- /* Carefully initialise all the strings in the notemap. */
- for (i = 0; i < MIDI_NOTE_NUM; i++)
- {
- (*notemap)[i] = (char *) NULL;
- }
-
- return notemap;
- }
-
- /* Frees the strings in a notemap. */
- static void
- notemap_delete_entries(Notemap *notemap)
- {
- register unsigned int i;
-
- /* Ensure that we've been given something to delete. */
- if (notemap != (Notemap *) NULL)
- {
- /* For each string in the notemap. */
- for (i = 0; i < MIDI_NOTE_NUM; i++)
- {
- /* Check to see if we have to do anything. */
- if ((*notemap)[i] != (char *) NULL)
- {
- /* Free the storage and make the pointer difficult to reuse. */
- (*functions->myfree)((*notemap)[i],
- strlen((*notemap)[i]) + 1);
- (*notemap)[i] = (char *) NULL;
- }
- }
- }
- }
-
- /* Frees an entire notemap structure (including the strings). */
- static void
- notemap_delete(Notemap *notemap)
- {
- /* Ensure that we've been given something to delete. */
- if (notemap != (Notemap *) NULL)
- {
- /* Delete the entries, and free the storage for the notemap. */
- notemap_delete_entries(notemap);
- (*functions->myfree)(notemap, sizeof(Notemap));
- }
- }
-
- /* Load a notemap from the file. If an error occurs, an incomplete
- notemap isn't deleted. */
- static void
- notemap_load(long file, /* Open file. */
- Notemap *notemap) /* Notemap to fill in. */
- {
- char file_id[ID_LEN]; /* File ID. */
- ULONG offset = 0; /* Offset to name map entries. */
- ULONG next = 0; /* Next pointer. */
-
- /* Ensure that the file id is one for a note map. */
- if ((*functions->fastread)(file, file_id, ID_LEN) < ID_LEN)
- {
- /* Failed to read the correct number of bytes for the file id. */
- return;
- }
- if (strncmp(file_id, "NTMP", ID_LEN) != 0)
- {
- /* Incorrect id */
- return;
- }
-
- /* Skip over the file length */
- if ((*functions->fastseek)(file, sizeof(ULONG), OFFSET_CURRENT) < 0)
- {
- /* Seek failed */
- return;
- }
-
- /* Read the offset for the note map entry data. */
- if ((*functions->fastread)(file, (UBYTE *)&offset, sizeof(offset)) < sizeof(offset))
- {
- /* Failed to read the correct number of bytes for the offset. */
- return;
- }
-
- /* Skip to the note map entries. Don't bother checking the
- map id or record length. */
- if ((*functions->fastseek)(file, offset+12, OFFSET_CURRENT) < 0)
- {
- /* Seek failed. */
- return;
- }
-
- /* We've made it this far, assume that we have a valid note map file. */
-
- /* Read in entries as long as the ``next'' pointer is not 0. */
- do {
- /* Notemap entry to be read from file. */
- struct NotemapFileEntry entry;
-
- /* Size of storage for the note's name. */
- size_t len;
-
- /* Read the ``next'' pointer and note map entry. */
- if ((*functions->fastread)(file, (UBYTE *)&next, sizeof(next)) < sizeof(next))
- {
- /* Failed to read the correct number of bytes for the ``next'' pointer. */
- return;
- }
- if ((*functions->fastread)(file, (UBYTE *)&entry, sizeof(entry)) < sizeof(entry))
- {
- /* Failed to read the correct number of bytes for an entry. */
- return;
- }
-
- /* Store the note name in the note map. */
-
- /* Allocate some memory for the new name. */
- len = strlen(entry.name);
- (*notemap)[entry.note] = (char *)(*functions->myalloc)(len + 1, MEMF_CLEAR);
- if ((*notemap)[entry.note] == (char *)NULL)
- {
- /* Allocation failed. */
- return;
- }
-
- /* Copy the string into the newly allocated memory and null terminate the
- string. */
- strcpy((*notemap)[entry.note], entry.name);
- (*notemap)[entry.note][len] = '\0';
-
- } while (next != 0);
-
- return;
- }
-
- /* -------------------------------------------------------------------- */
- /* SPLITTING TRACKS */
- /* -------------------------------------------------------------------- */
-
- /* For splitting the tracks, I maintain two separate structures, one for
- the note events, and one for the others (i.e. control change, etc.)
- The note events are stored in an array, with each element of the array
- corresponding to a particular MIDI note. The other events are all lumped
- in together. */
-
- /* Split a list of events into note events and other events. */
- static BOOL
- eventlist_split(struct Event *source, /* Pointer to first event in list */
- /* to be split. */
- struct Event **notes, /* Array of event lists, */
- /* one for each MIDI note. */
- struct Event **others) /* Handle for event list for */
- /* non-note events. */
- {
- struct NoteEvent *event;
-
- /* For each event in the list. */
- for (event = (struct NoteEvent *) source;
- event;
- event = (struct NoteEvent *) event->next)
- {
- /* If it's a MIDI performance event.*/
- if ((event->type & 0xf) == EVENT_VOICE)
- {
- /* Try to allocate a new event and check to see if we succeeded. */
- struct NoteEvent *new =
- (struct NoteEvent *)(*functions->allocevent)();
- if (new == (struct NoteEvent *) NULL)
- {
- /* Allocation failed. */
- return FALSE;
- }
-
- /* Initialise the new event. */
- *new = *event;
-
- /* Is it a note event? */
- if ((new->status & 0xff) == MIDI_NOTEON)
- {
- new->next = notes[new->value];
- notes[new->value] = new;
- }
- else /* It's some other sort of MIDI event. */
- {
- new->next = *others;
- *others = new;
- }
- }
- }
-
- return TRUE;
- }
-
- /* Shameless plug inserted into track notes by the accessory. */
- static const char *splitter_notes = "Created by Splitter Accessory";
-
- /* Storage for note to name conversion. */
- static char name[NOTE_NAME_LEN];
-
- /* Returns a text string given a midi note number. */
- static char *
- note_name(unsigned char note)
- {
- static char *note_names[] = {
- "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "Bb", "B"
- };
-
- sprintf(name, "%s%1ld", note_names[note % 12], (int) note / 12);
-
- return name;
- }
-
- /* Allocate, initialise and return a new track.
- If something goes wrong, returns NULL. */
- static struct Track *
- track_new(struct Track *old, /* Track to initialise from. */
- char *name, /* Name of the new track. */
- unsigned char note, /* Which MIDI note this corresponds to. */
- struct Event *events) /* Events for the new track. */
- /* In reverse order! */
- {
- /* Attempt to allocate the track, and check to see if we succeeded. */
- struct Track *track =
- (struct Track *)(*functions->createtrack)(1, 0);
- if (track == (struct Track *) NULL)
- {
- return (struct Track *) NULL;
- }
-
- /* Initialise the track from the fields of the supplied track. */
- track->next = (struct Track *) NULL;
-
- /* Keep the same channel in and out assignments. */
- track->channelin = old->channelin;
- track->channelout = old->channelout;
-
- /* Careful! createtrack() has already given the track a name. */
- (*functions->replacestring)(&(track->clip.name),
- name ? name : note_name(note));
- track->clip.notes =
- (struct String *)(*functions->allocstring)(splitter_notes);
-
- /* Highest and lowest notes for the clip are the same as the note. */
- track->clip.highnote = note;
- track->clip.lownote = note;
-
- /* Begin and end times. */
- track->clip.begin = 0;
- track->clip.end = events == (struct Event *) NULL ? 0 : events->time;
-
- /* Sort and add the events. */
- track->clip.events.first =
- (struct Event *)(*functions->sorteventlist)(events);
- track->clip.events.point = (struct Event *) NULL;
-
- return track;
- }
-
- /* Split a track according to the supplied notemap. It will add as many
- tracks as needed following the selected track. */
- static void
- track_split(struct Track *track, /* Track to be split. */
- Notemap *notemap) /* Note map to use. */
- {
- int i;
-
- /* List of events for non-note MIDI events. */
- struct Event *others = (struct Event *) NULL;
-
- /* Array of lists of events, one for each MIDI note. */
- struct Event *notes[MIDI_NOTE_NUM];
-
- /* Initialise the event list array. */
- for (i = 0; i < MIDI_NOTE_NUM; i++)
- {
- notes[i] = (struct Event *) NULL;
- }
-
- /* Try to separate out the events in the track. */
- if (eventlist_split(track->clip.events.first, notes, &others))
- {
- /* List of new tracks */
- struct Track *new_tracks = NULL;
-
- register unsigned int i;
-
- /* Were there any non-note events? */
- if (others != (struct Event *) NULL)
- {
- new_tracks = track_new(track, "Other Events",
- (unsigned char) 0,
- others);
- }
-
- /* Create tracks for each of the lists of events. */
- for (i = 0; i < MIDI_NOTE_NUM; i++)
- {
- /* If there are notes for the track, notes[i] will be non-null. */
- if (notes[i] != (struct Event *) NULL)
- {
- /* Make the new track. */
- struct Track *new = track_new(track,
- (*notemap)[i],
- (unsigned char) i,
- notes[i]);
-
- /* Stick it at the start of the list so far. */
- new->next = new_tracks;
- new_tracks = new;
- }
- }
-
- /* Splice in the list of new tracks. */
- track->next = (struct Track *)(*functions->List_Cat)(new_tracks, track->next);
- }
- }
-
- /* -------------------------------------------------------------------- */
- /* INTERFACE */
- /* -------------------------------------------------------------------- */
-
- /* I built this interface by hand as well. Does anyone have a favorite
- GUI builder? */
-
- static const struct IntuiText itext1 = {
- 4,0,JAM1,
- 12,1,
- NULL,
- "Load Note Map File",
- NULL
- };
-
- static const struct Gadget gadget1 = {
- NULL,
- 15, 16,
- 168, 9,
- (ULONG) NULL,
- RELVERIFY+GADGIMMEDIATE,
- BOOLGADGET,
- NULL,
- NULL,
- &itext1,
- (ULONG) NULL,
- NULL,
- 1,
- NULL
- };
-
- static const struct IntuiText itext2 = {
- 4,0,JAM1,
- 4,1,
- NULL,
- "Split Selected Track",
- NULL
- };
-
- static const struct Gadget gadget2 = {
- &gadget1,
- 15, 27,
- 168, 9,
- (ULONG) NULL,
- RELVERIFY+GADGIMMEDIATE,
- BOOLGADGET,
- NULL,
- NULL,
- &itext2,
- (ULONG) NULL,
- NULL,
- 2,
- NULL
- };
-
- static const struct IntuiText itext3 = {
- 4,0,JAM1,
- 28, 1,
- NULL,
- "Clear Notemap",
- NULL
- };
-
- static const struct Gadget gadget3 = {
- &gadget2,
- 15, 38,
- 168, 9,
- (ULONG) NULL,
- RELVERIFY+GADGIMMEDIATE,
- BOOLGADGET,
- NULL,
- NULL,
- &itext3,
- (ULONG) NULL,
- NULL,
- 3,
- NULL
- };
-
- /* Start of gadget list. */
- #define gadget_list (&gadget3)
-
- /* Close the splitter window. */
- __geta4 /* Callback function. */
- splitter_close(void)
- {
- /* Ensure that we have something to close. */
- if (splitter.accessory.window)
- {
- struct IntuiMessage *message;
-
- (*functions->EmbossOff)(splitter.accessory.window,1);
- (*functions->EmbossOff)(splitter.accessory.window,2);
- (*functions->EmbossOff)(splitter.accessory.window,3);
- (*functions->EmbossWindowOff)(splitter.accessory.window);
-
- /* Remember where we were in case we're reopened later. */
- splitter.accessory.left = splitter.accessory.window->LeftEdge;
- splitter.accessory.top = splitter.accessory.window->TopEdge;
-
- /* Make it hard to send us messages and eat up any that are pending. */
- splitter.accessory.window->UserPort = 0;
- ModifyIDCMP(splitter.accessory.window,0);
- WaitTOF();
- WaitTOF();
- WaitTOF();
- WaitTOF();
- WaitTOF();
- Forbid();
- while (message = (struct IntuiMessage *)GetMsg(functions->window->UserPort))
- {
- ReplyMsg((struct Message *)message);
- }
- (*functions->FlashyCloseWindow)(splitter.accessory.window);
- splitter.accessory.window = NULL;
- Permit();
- }
-
- return(1);
- }
-
- static const char *title = "Splitter v1.0";
-
- /* Open the splitter window. */
- __geta4 /* Callback function. */
- splitter_open(void)
- {
- /* Use v37+ style window tags to specify the new window. */
- const struct TagItem tags[] = {
- {WA_Left, splitter.accessory.left},
- {WA_Top, splitter.accessory.top},
- {WA_Width, 198},
- {WA_Height, 53},
- {WA_DetailPen, 5},
- {WA_BlockPen, 1},
- {WA_IDCMP, GADGETUP|CLOSEWINDOW},
- {WA_DragBar, FALSE},
- {WA_DepthGadget, FALSE},
- {WA_CloseGadget, FALSE},
- {WA_Activate, TRUE},
- {WA_NoCareRefresh, TRUE},
- {WA_Borderless, TRUE},
- {WA_Gadgets, (ULONG) gadget_list},
- {WA_Checkmark, (ULONG) NULL},
- {WA_Title, (ULONG) NULL},
- {WA_ScreenTitle, (ULONG) title},
- {WA_CustomScreen, (ULONG) functions->screen}
- };
-
- /* Attempt to open the window, and check to see if we were successful. */
- splitter.accessory.window = (struct Window *)OpenWindowTagList(NULL, &tags);
- if (splitter.accessory.window != (struct Window *) NULL)
- {
- /* Set up communication. */
- splitter.accessory.window->UserPort = functions->window->UserPort;
- ModifyIDCMP(splitter.accessory.window,functions->window->IDCMPFlags);
-
- (*functions->EmbossWindowOn)(splitter.accessory.window,
- WINDOWCLOSE|WINDOWDEPTH|WINDOWDRAG,
- "Splitter",(short)-1,(short)-1,0,0);
- (*functions->EmbossOn)(splitter.accessory.window,1,1);
- (*functions->EmbossOn)(splitter.accessory.window,2,1);
- (*functions->EmbossOn)(splitter.accessory.window,3,1);
- }
-
- return((long)splitter.accessory.window);
- }
-
- /* Gather and process user input from the splitter window. */
- __geta4 /* Callback function. */
- splitter_edit(struct IntuiMessage *message) /* Message to process. */
- {
- struct Window *window = message->IDCMPWindow;
- struct Gadget *gadget;
- long class,code;
-
- class = message->Class;
- code = message->Code;
- gadget = (struct Gadget *) message->IAddress;
- ReplyMsg((struct Message *)message);
- class = (*functions->SystemGadgets)(window,class,gadget,code);
-
- if (class == CLOSEWINDOW)
- {
- (void) splitter_close();
- return 0;
- }
- else if (class == GADGETUP)
- {
- switch (gadget->GadgetID)
- {
- case 1: /* Load Note Map File */
- {
- char filename[255];
-
- /* Get the filename */
- (*functions->FileName)(filename,"Load Note Map File:","drummap",
- functions->screen,
- FILES_OPEN|FILES_DELETE|FILES_TYPE,0,0);
- if (filename[0])
- {
- /* Attempt to open the file and check to see if we
- succeeded. */
- long file = (*functions->fastopen)(filename,MODE_OLDFILE);
- if (file)
- {
- if ((*functions->areyousure)("replace the note map?"))
- {
- (*functions->openwait)();
- notemap_delete_entries(splitter.notemap);
- notemap_load(file, splitter.notemap);
- (*functions->closewait)();
- }
- (*functions->fastclose)(file);
- }
- else
- {
- accessory_error(splitter.accessory.window,
- "Couldn't open file for reading");
- }
- }
- }
- break;
- case 2: /* Split Selected Track */
- {
- if (functions->groupid != 0) /* Group selected? */
- {
- accessory_error(splitter.accessory.window,
- "Can't split a group");
- }
- else if (functions->selectedtrack) /* Track selected? */
- {
- (*functions->openwait)();
- track_split(functions->selectedtrack, splitter.notemap);
- (*functions->display)(0x1000000);
- (*functions->closewait)();
- }
- else /* No track selected. */
- {
- accessory_error(splitter.accessory.window,
- "You must select a track for splitting");
- }
- }
- break;
- case 3:
- {
- if ((*functions->areyousure)("clear the note map?"))
- {
- (*functions->openwait)();
- notemap_delete_entries(splitter.notemap);
- (*functions->closewait)();
- }
- }
- }
- }
- return 1;
- }
-
- /* Free the notemap. */
- __geta4 /* Callback function. */
- splitter_remove(void)
- {
- notemap_delete(splitter.notemap);
- }
-
- struct Accessory *
- inittoolmaster(void)
- {
- memset((char *)&splitter,0,sizeof(struct Splitter));
- splitter.accessory.left = INITIAL_LEFT;
- splitter.accessory.top = INITIAL_TOP;
- splitter.accessory.id = MAKE_IDS("SPLT");
- splitter.accessory.next = 0;
- splitter.accessory.image = &splitter_image;
- splitter.accessory.onimage = &splitter_onimage;
- splitter.accessory.open = splitter_open;
- splitter.accessory.close = splitter_close;
- splitter.accessory.edit = (no_prototype) splitter_edit;
- splitter.accessory.remove = splitter_remove;
- strcpy(splitter.accessory.name, "Splitter");
- splitter.notemap = notemap_new();
- if (splitter.notemap == (struct Notemap *) NULL)
- {
- return (struct Accessory *) NULL;
- }
-
- return(&splitter.accessory);
- }
-